package org.ssssssss.magicapi.dubbo;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.service.GenericService;
import org.ssssssss.magicapi.core.annotation.MagicModule;
import org.ssssssss.script.annotation.Comment;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author August.Zhang
 * @version v1.0.0
 * @date 2023/10/19 17:02
 * @since JDK 1.8
 */
@MagicModule("dubbo")
public class DubboModule {

    private static final String GENERIC_SERVICE_NOT_FOUND_ERROR = "%s全路径错误！";

    private static final Map<String, GenericService> DUBBO_INTERFACE_MAP = new ConcurrentHashMap<>();

    public DubboModule(MagicDubboProperties magicDubboProperties) {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName(magicDubboProperties.getAppName());

        List<MagicDubboProperties.DubboServiceProperties> serviceList = magicDubboProperties.getServiceList();
        if (serviceList != null && !serviceList.isEmpty()) {
            serviceList.forEach(service -> {
                resgiterDubboInterface(applicationConfig, service);
            });
        }
    }

    /**
     * 注册dubbo接口
     */
    public void resgiterDubboInterface(ApplicationConfig applicationConfig, MagicDubboProperties.DubboServiceProperties dubboServices) {
        List<String> services = dubboServices.getServices();
        if (services != null && !services.isEmpty()) {
            String registerAddress = dubboServices.getRegisterAddress();
            RegistryConfig registryConfig = new RegistryConfig();
            registryConfig.setAddress("zookeeper://" + registerAddress);
            for (String path : services) {
                ReferenceConfig<GenericService> referenceConfig = new ReferenceConfig<>();
                referenceConfig.setApplication(applicationConfig);
                referenceConfig.setRegistry(registryConfig);
                referenceConfig.setInterface(path);
                referenceConfig.setGeneric("true");
                // 获取 Dubbo 泛化服务
                DUBBO_INTERFACE_MAP.put(path, referenceConfig.get());
            }
        }
    }

    @Comment("dubbo 泛化调用")
    public Object invoke(String path, List<String> parameterTypes, List<Object> params) {
        int i = path.lastIndexOf(".");
        String interfaceName = path.substring(0, i);
        String methodName = path.substring(i + 1);
        GenericService genericService = DUBBO_INTERFACE_MAP.get(interfaceName);
        if (genericService == null) {
            throw new IllegalArgumentException(String.format(GENERIC_SERVICE_NOT_FOUND_ERROR, path));
        }
        return genericService.$invoke(methodName, parameterTypes.toArray(new String[0]), params.toArray(new Object[0]));
    }

}
